/**
**************************************************************************************
*Founder Effect                                                                      *
*Copyright (C) 2006-2007, 5d Studios (www.5d-Studios.com)                            *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#pragma once

#include <map>
#include <string>
#include <algorithm>
#include "Animation.h"

// max directions
const int MAX_DIRECTIONS = 4;

/**
========================
Holds an animation for a given direction
========================
*/
class ModelDirections
{
public:
    ModelDirections() {};
    // the four directions, each have an animation
    Animation dirs[MAX_DIRECTIONS];
	
    /** Add a direction with an animation */
	void AddDirection( int i, int fps, int row, int col, int amount)
	{
		dirs[i].Set( fps, row, col, amount );
	}

    /** Get this directions animation */
	Animation* GetAnim(int i) { return &dirs[i]; };

    virtual ~ModelDirections() {};
};


/**
=========================
Holds model directions for a given state
=========================
*/
class ModelStates 
{
public:
    ModelStates() {};
    typedef std::map< std::string, ModelDirections*> type_ModelStates;
    // Each model has states, each state can have four directions
    type_ModelStates states;

    /** Add a state, with a modelDirection */
    void AddState( const std::string &state, ModelDirections* mdir )
	{
		states[state] = mdir;
	}

    /** Get a states modelDirection */
    ModelDirections* GetState( const std::string &s) { return states[s]; };

    virtual ~ModelStates() {
        type_ModelStates::iterator it = states.begin();
        for(; it != states.end(); it++ )
            if(it->second)
                delete it->second;
    };
};


/**
============================
The actual model for an entity
============================
*/
class Model 
{
public:
    Model() {
        m_currentState = "IDLE";
        m_currentDir = 0;
    };
    Model(Image image) : m_image( image) {
        m_currentState = "IDLE";
        m_currentDir = 0;
    };


    /** Animate the model */
	void Update(long dt) {
		m_states.GetState( m_currentState )->GetAnim( m_currentDir )->Update( dt );
	}

    /** Set the active state */
	void SetCurrentState( const std::string &state ) {
		m_currentState = state;
	}

    /** Set the active direction */
	void SetCurrentDirection( int dir )
	{
		m_currentDir = dir;
	}

    /** Set the image */
    void SetImage(Image image) { m_image = image; };

    /** Get the image */
	Image GetImage() {
        return m_image;
	}

    /** Get the current frame */
    int GetCurrentFrame() {
        return m_states.GetState( m_currentState )->GetAnim( m_currentDir )->GetFrame();
    }

    /** Get the current row (in the image) */
    int GetRow() {
        return m_states.GetState( m_currentState )->GetAnim( m_currentDir )->GetRow();
    }

    /** Add a state */
    void AddState( const std::string &state, ModelDirections* mdir ) {
        m_states.AddState( state, mdir );
    }

private:
    // the possible states this
    // model can be in
    ModelStates	m_states;

    // the current state
    std::string		m_currentState;
    // the current direction
	int		        m_currentDir;

    // the texture that belongs to this model
    Image m_image;
public:
    virtual ~Model(void) {};
};
